package com.qc31.monitorlib.movepoint

import com.amap.api.maps.AMap
import com.amap.api.maps.CameraUpdateFactory
import com.amap.api.maps.model.BitmapDescriptor
import com.amap.api.maps.model.LatLng
import com.amap.api.maps.model.Marker
import com.amap.api.maps.model.MarkerOptions
import java.util.*

/** @author joker @date 2022/7/19$ 16:03$ */
class MovePointOverlay(private val mAMap: AMap, private val bitmapDesc: BitmapDescriptor) {
    //线程锁
    private val mLock = Object()

    //图标点下标
    private var index = 0

    //记录当前状态
    private var STATUS: Status? = null

    //移动Marker
    private var mMoveMarker: Marker? = null

    //全部轨迹点
    private var mPoints: LinkedList<LatLng> = LinkedList()

    //开启
    private var runnable: PointRunnable? = null

    //全部点的总数量
    private var pointTotal = 0

    /** 添加一个移动图标 */
    private fun addCarMarker(startPoint: LatLng) {
        val markerOptions = MarkerOptions()
            .setFlat(true) //设置Marker覆盖物是否平贴地图
            .icon(bitmapDesc)
            .position(startPoint)
            .anchor(0.5f, 0.5f)
            .rotateAngle(getAngle(0).toFloat())
        mMoveMarker = mAMap.addMarker(markerOptions)
    }

    /** 重置状态 */
    fun reset() {
        if (STATUS == Status.PAUSE || STATUS == Status.MOVING) {
            STATUS = Status.RESET
        }
        index = 0
        if (mMoveMarker != null) {
            val latLng = mPoints[0]
            mMoveMarker!!.rotateAngle = MovePointUtil.getAngle(latLng, mPoints[1]).toFloat()
            mMoveMarker!!.position = latLng
            mAMap.animateCamera(CameraUpdateFactory.newLatLng(latLng))
        }
        pointListener?.startPause(false)
    }

    /** 开始 */
    private fun startMove() {
        if (STATUS == Status.PAUSE || STATUS == Status.RESET) {
            STATUS = Status.MOVING
            synchronized(mLock) { mLock.notify() }
        } else if (STATUS == Status.READY || STATUS == Status.FINISH) {
            restart()
        } else if (STATUS == Status.SEEKBAR) {
            if (runnable == null) {
                restart()
            } else {
                STATUS = Status.MOVING
                synchronized(mLock) { mLock.notify() }
            }

        }
    }

    /** 重启 */
    private fun restart() {
        index = 0
        exitFlag = true
        STATUS = Status.READY
        runnable = PointRunnable()
        Thread(runnable).start()
    }

    /** Start pause */
    fun startPause() {
        if (STATUS == Status.MOVING) {
            STATUS = Status.PAUSE
            pointListener?.startPause(false)
        } else {
            startMove()
            pointListener?.startPause(true)
        }
    }

    /** Pause move */
    fun pauseMove() {
        if (STATUS == Status.MOVING) {
            STATUS = Status.PAUSE
        }
    }

    /** 标注拖动进度 */
    fun seekbarMove() {
        STATUS = Status.SEEKBAR
        pointListener?.startPause(false)
    }

    /** 停止移动move */
    private fun stopMove() {
        if (STATUS == Status.MOVING || STATUS == Status.PAUSE) {
            STATUS = Status.FINISH
        }
        pointListener?.startPause(false)
    }

    /** 设置定位点数据 */
    fun setPoints(points: List<LatLng>) = synchronized(mLock) {
        if (points.size >= 2) {
            stopMove()
            mPoints.clear()
            mPoints.addAll(points)
            addCarMarker(mPoints[0])
            STATUS = Status.READY
        }
        pointTotal = mPoints.size - 1
    }

    /** @param index 下标 */
    fun change(index: Int) {
        this.index = index
        mMoveMarker!!.position = mPoints[index]
        if (index == mPoints.size - 1) {
            mMoveMarker!!.rotateAngle = getAngle(index - 1).toFloat()
        } else {
            mMoveMarker!!.rotateAngle = getAngle(index).toFloat()
        }
    }

    /** Moving 小车移动主要逻辑 */
    private fun moving() {
        if (index < pointTotal) {
            if (STATUS == Status.PAUSE) {
                pause()
            }
            if (STATUS == Status.FINISH || STATUS == Status.RESET) {
                pause()
                return
            }
            val fromPoint = mPoints[index]
            val toPoint = mPoints[index + 1]
            mMoveMarker!!.rotateAngle = MovePointUtil.getAngle(fromPoint, toPoint).toFloat()
            mMoveMarker!!.position = fromPoint
            pointListener?.current(index, fromPoint, toPoint)

            val slope = MovePointUtil.getSlope(fromPoint, toPoint)
            val isYReverse = fromPoint.latitude > toPoint.latitude
            val isXReverse = fromPoint.longitude > toPoint.longitude
            val intercept = MovePointUtil.getInterception(slope, fromPoint)
            val xMoveDistance =
                if (isXReverse) {
                    MovePointUtil.getXMoveDistance(slope)
                } else {
                    -1 * MovePointUtil.getXMoveDistance(slope)
                }
            val yMoveDistance =
                if (isYReverse) {
                    MovePointUtil.getYMoveDistance(slope)
                } else {
                    -1 * MovePointUtil.getYMoveDistance(slope)
                }

            var lat = fromPoint.latitude
            var lng = fromPoint.longitude
            while (lat >= toPoint.latitude == isYReverse && lng >= toPoint.longitude == isXReverse) {
                if (STATUS == Status.PAUSE) {
                    pause()
                }
                if (STATUS == Status.FINISH || STATUS == Status.RESET || STATUS == Status.SEEKBAR) {
                    pause()
                    return
                }
                var latLng: LatLng
                when (slope) {
                    Double.MAX_VALUE -> {
                        latLng = LatLng(lat, lng)
                        lat -= yMoveDistance
                    }
                    0.0 -> {
                        latLng = LatLng(lat, lng - xMoveDistance)
                        lng -= xMoveDistance
                    }
                    else -> {
                        latLng = LatLng(lat, (lat - intercept) / slope)
                        lat -= yMoveDistance
                    }
                }
                if (latLng.latitude == 0.0 && latLng.longitude == 0.0) {
                    continue
                }
                pointListener?.moving(latLng)
                mMoveMarker?.position = latLng
                try {
                    Thread.sleep(MovePointUtil.TIME_INTERVAL.toLong())
                } catch (e: InterruptedException) {
                    e.printStackTrace()
                }
            }
            index++
            moving()
        } else {
            STATUS = Status.FINISH
            pointListener?.finish()
        }
    }

    /** 暂停线程 */
    private fun pause() {
        try {
            mLock.wait()
        } catch (e: InterruptedException) {
            e.printStackTrace()
        }
    }

    /** 销毁资源 */
    fun destroy() {
        stopMove()
        exitFlag = false
        runnable = null
        mPoints.clear()
    }

    /** 根据经纬点下标获取图标转的角度 */
    private fun getAngle(startIndex: Int): Double {
        if (startIndex + 1 >= mPoints.size) return -1.0
        val startPoint = mPoints[startIndex]
        val endPoint = mPoints[startIndex + 1]
        return MovePointUtil.getAngle(startPoint, endPoint)
    }

    /** 线程状态 START 开始 PAUSE 暂停 MOVING 移动中 FINISH 结束 */
    internal enum class Status {
        READY, PAUSE, MOVING, FINISH, RESET, SEEKBAR
    }

    private inner class PointRunnable : Runnable {
        override fun run() {
            while (exitFlag && STATUS != Status.FINISH) {
                STATUS = Status.MOVING
                synchronized(mLock) { moving() }
            }
        }
    }

    private var exitFlag = true

    //移动事件监听
    private var pointListener: MovePointListener? = null
    fun setMovePointListener(pointListener: MovePointListener?) {
        this.pointListener = pointListener
    }
}